#include <QMouseEvent>
#include "PythonEditor.h"
#include "Include/Lexers.h"
#include "Include/Plugins.h"
#include "Include/Project.h"
#include "Include/IRopeProject.h"
#include "ErrorModel.h"


namespace Plugins {

PythonEditor::PythonEditor(QWidget *parent):
    TextEditor(parent),
    _hightliteWord(""),
    _hightliteWordStart(0)
{
    init("Python");
    _model = new ErrorModel(QList<ErrorItem>());

    _wordHightLite = indicatorDefineOld(QsciScintilla::INDIC_SQUIGGLE);
    setIndicatorDrawUnderOld(true, _wordHightLite);
    setIndicatorForegroundColorOld(Qt::blue, _wordHightLite);
}

PythonEditor::~PythonEditor()
{
    if (_project && _project->rope()){
        _project->rope()->closeFile(_fileName);
    }
}

void PythonEditor::onLoad()
{
    _file = _project->rope()->openFile(_fileName);
    connect(_file, SIGNAL(errorListComplete(QList<ErrorItem>)), SLOT(onErrorListComplete(QList<ErrorItem>)));
    connect(_file, SIGNAL(autoComplite(CompletitionList)), SLOT(onAutoComplite(CompletitionList)));
    connect(_file, SIGNAL(findImplementationComplite(QString, int)), SLOT(onFindImplementationComplite(QString, int)));
    checkErrors();
}

void PythonEditor::onSave()
{
    checkErrors();
}

void PythonEditor::onErrorListComplete(const QList<ErrorItem> & list)
{
    int sev = 0;
    clearErrors();
    foreach(ErrorItem err, list){
        int nsev = getByCode(err.type);
        markErrors(err.lineNo, err.message, nsev);
        if (sev < nsev)
            sev = nsev;
    }
    if (_model)
        delete _model;
    _model = new ErrorModel(list, this);
    emit errorListChanged(_model);
    emit severityChanged(sev);
}

void PythonEditor::checkErrors()
{
    _file->errorsList();
}

int PythonEditor::getByCode(const QString & code)
{
    int sev = 0;
    if (code[0] == 'C')
        sev += Convection;
    if (code[0] == 'W')
        sev += Warning;
    if (code[0] == 'E')
        sev += Error;
    return sev;
}

void PythonEditor::onCodeComplite()
{
    int pos = SendScintilla(QsciScintilla::SCI_GETCURRENTPOS);
    _file->autocompletitionList(text(), pos);
}

void PythonEditor::onAutoComplite(const CompletitionList & list)
{
    SendScintilla(QsciScintilla::SCI_AUTOCSETSEPARATOR, 46);
    SendScintilla(QsciScintilla::SCI_AUTOCSETTYPESEPARATOR, ':');
    QStringList typedList;
    foreach(QString it, list.items){
        QStringList spl = it.split('|');
        if (spl.length() > 1){
            QString t = getType(spl[1]);

            typedList.append(spl[0]+":"+t);
        }
    }

    SendScintilla(QsciScintilla::SCI_AUTOCSHOW, list.word.length(), qPrintable(typedList.join(".")));
}

QString PythonEditor::getType(const QString & named)
{
    if (named == "function")
        return "3";
    if (named == "module")
        return "4";
    if (named == "class")
        return "2";
    return "1";
}

bool PythonEditor::reset()
{
    if (SendScintilla(QsciScintilla::SCI_AUTOCACTIVE)){
        SendScintilla(QsciScintilla::SCI_AUTOCCANCEL);
        return true;
    }
    return false;
}

void PythonEditor::activate()
{
    TextEditor::activate();
    emit errorListChanged(_model);
}

void PythonEditor::mouseMoveEvent(QMouseEvent *e)
{
    if (e->modifiers() & Qt::ControlModifier){
        QString word = wordAtPoint(e->pos());
        int pos = SendScintilla(QsciScintilla::SCI_POSITIONFROMPOINTCLOSE, e->x(), e->y());
        int wordStart;
        int wordEnd;

        if (!word.isEmpty() && pos > 0){
            wordStart = SendScintilla(QsciScintilla::SCI_WORDSTARTPOSITION, pos, true);
            wordEnd = SendScintilla(QsciScintilla::SCI_WORDENDPOSITION, pos, true);
        }

        if (!word.isEmpty() && pos > 0 && (word != _hightliteWord || _hightliteWordStart != wordStart)){
            SendScintilla(QsciScintilla::SCI_SETINDICATORCURRENT, _wordHightLite);
            SendScintilla(QsciScintilla::SCI_INDICATORCLEARRANGE, 0, text().length());

            _hightliteWord = word;
            _hightliteWordStart = wordStart;

            int sline = 0, sindex = 0;
            lineIndexFromPosition(wordStart, &sline, &sindex);

            int eline = 0, eindex = 0;
            lineIndexFromPosition(wordEnd, &eline, &eindex);
            fillIndicatorRange(sline, sindex, eline, eindex, _wordHightLite);
        }
    } else {
        if (!_hightliteWord.isEmpty() || _hightliteWordStart){
            SendScintilla(QsciScintilla::SCI_SETINDICATORCURRENT, _wordHightLite);
            SendScintilla(QsciScintilla::SCI_INDICATORCLEARRANGE, 0, text().length());
            _hightliteWord = "";
            _hightliteWordStart = 0;
        } else {
            TextEditor::mouseMoveEvent(e);
        }
    }
}

void PythonEditor::mousePressEvent(QMouseEvent *e)
{
    if (e->modifiers() & Qt::ControlModifier){
        QString word = wordAtPoint(e->pos());
        int pos = SendScintilla(QsciScintilla::SCI_POSITIONFROMPOINTCLOSE, e->x(), e->y());
        int wordStart = SendScintilla(QsciScintilla::SCI_WORDSTARTPOSITION, pos, true);
        if (!word.isEmpty() && pos > 0 && word == _hightliteWord && _hightliteWordStart == wordStart){
            _file->findImplementation(text(), pos);
            return;
        }
    }
    TextEditor::mousePressEvent(e);
}

void PythonEditor::onFindImplementationComplite(const QString &file, int offset)
{
    if (file != "" && offset > 0)
        emit fileNavigate(file, offset);
}

}
